package com.alstudio.module.xmpp.protocol.xmpp.parser.message;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;

import org.xmlpull.v1.XmlPullParserException;

import android.text.TextUtils;

import com.alstudio.module.xmpp.protocol.xmpp.ALXmppEventListener;
import com.alstudio.module.xmpp.protocol.xmpp.data.ALPhoto;
import com.alstudio.module.xmpp.protocol.xmpp.packact.ALMessage;
import com.alstudio.module.xmpp.protocol.xmpp.parser.BaseParser;
import com.alstudio.pojo.module.ButtonInfo;
import com.alstudio.pojo.module.user.User;
import com.alstudio.utils.formater.numeric.ALNumericUtils;
import com.alstudio.utils.log.ALLog;
import com.alstudio.utils.xml.BaseXmlParser;
import com.alstudio.utils.xml.BaseXmlParser.XmlParseCallback;

public class ALMessageParser extends BaseParser implements XmlParseCallback {

	private ALMessage msg;
	private ALMessageXmlParser mParser;
	private String type;
	private String ip = null;
	private int port = -1;

	private final String IP_TAG = "ip";
	private final String PORT_TAG = "port";
	private final String NAT_TAG = "nataddr";
	private final String LAN_TAG = "lanaddr";
	private final String TRANSFER_TAG = "turnaddr";

	protected final String JID_TAG = "jid";
	protected final String NICK_TAG = "nick";
	protected final String SEX_TAG = "sex";
	protected final String AVATAR_TAG = "avatar";
	protected final String LAST_ONLINE_TAG = "lastonline";
	protected final String AGE_TAG = "age";
	protected final String PROVICE_TAG = "province";
	protected final String CITY_TAG = "city";
	protected final String GLAMOUR_TAG = "glamour";
	protected final String ITEMS_TAG = "items";
	protected final String ITEM_TAG = "item";
	protected final String TYPE_TAG = "type";

	protected final String VCARD_TAG = "vcard";
	protected final String PHOTOS_TAG = "photos";
	protected final String PHOTO_TAG = "photo";
	protected final String SIG_TAG = "sig";

	protected final String ONLINE_TAG = "online";
	protected final String IS_FRIEND_TAG = "isfriend";
	protected final String IN_BLACK_LIST_TAG = "inblacklist";
	protected final String VAUTHED_TAG = "vauthed";
	protected final String FAN_SNUM_TAG = "fansnum";
	//
	protected final String STATUS_TAG = "status";
	protected final String VOICE_TAG = "voice";
	protected final String ZODIAC_TAG = "zodiac";
	protected final String EMAIL_TAG = "email";
	protected final String GOLD_TAG = "gold";
	protected final String SILVER_TAG = "silver";

	protected final String BIRTHDAY_TAG = "birthday";
	protected final String BACKGROUND_TAG = "background";

	protected final String VIP_LEVEL_TAG = "viplevel";
	protected final String VALUE_TAG = "value";
	protected final String IS_SPECIAL_TAG = "isspecial";
	protected final String STAR_TAG = "star";
	protected final String POINTS_TAG = "points";
	protected final String COUNT_TAG = "count";
	protected final String VERSION_TAG = "version";

	protected final String DELETE_TAG = "delete";
	protected final String FROM_AVATAR = "fromavatar";

	private User user;
	private int deleteType = -1;
	private ArrayList<ButtonInfo> buttonList = new ArrayList<ButtonInfo>();
	private ArrayList<ALPhoto> photos;

	public ALMessageParser(ALMessage msg, String stream,
			ALXmppEventListener listener) {
		// TODO Auto-generated constructor stub
		this.stream = stream;
		this.msg = null;
		this.type = null;
		this.msg = msg;
		user = null;
		type = msg.getMsgType();
		mListener = listener;
		photos = null;
		checkALMessageType();
		try {
			mParser = new ALMessageXmlParser(stream, this);
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected class ALMessageXmlParser extends BaseXmlParser {

		protected ALMessageXmlParser(String xml, XmlParseCallback callback)
				throws XmlPullParserException {
			// TODO Auto-generated constructor stub
			createParser(xml);
			setXmlParseCallback(callback);
		}

		protected void start() throws XmlPullParserException, IOException {
			startParse();
		}

	}

	public void startParseALMessage() {
		ALLog.d("start parsing ALMessage...");

		try {
			mParser.start();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void onTagStart(String tag) {
		// TODO Auto-generated method stub
		try {
			if (tag.equals("fromnick")) {
				msg.setFromNick(mParser.readText());
			} else if (tag.equals("body")) {
				msg.setBody(readText());
				msg.setLinkBody2(msg.getBody());
				msg.setLinkBody(msg.getBody());
				msg.setBob(msg.getBody());
			} else if (tag.equals("id")) {
				msg.setMsgId(mParser.readText());
			} else if (tag.equals(JID_TAG)) {
				msg.setJid(mParser.readText());
				if (user != null) {
					user.setJid(msg.getJid());
				}
			} else if (tag.equals(NICK_TAG)) {
				msg.setFromNick(mParser.readText());
				if (user != null) {
					user.setNick(msg.getFromNick());
				}
			} else if (tag.equals(PROVICE_TAG)) {
				// 省会
				if (user != null) {
					user.setProvince(readText());
				}
			} else if (tag.equals(CITY_TAG)) {
				// 城市
				if (user != null) {
					user.setCity(readText());
				}
			} else if (tag.equals(AGE_TAG)) {
				// 年龄
				if (user != null) {
					user.setAge(readText());
				}
			} else if (tag.equals(SEX_TAG)) {
				String sex = readText();
				msg.setSex(sex);
				// 性别
				if (user != null) {
					user.setSex(sex);
				}
			} else if (tag.equals(SIG_TAG)) {
				// 签名
				if (user != null) {
					user.setSignature(readText());
				}
			} else if (tag.equals(VAUTHED_TAG)) {
				String vauth = readText();
				msg.setVauth(vauth);
				// V认证状态
				if (user != null) {
					user.setVauthed(ALNumericUtils.parseInt(vauth, 0));
				}
			} else if (tag.equals(GOLD_TAG)) {
				// 金币
				if (user != null) {
					user.setGold(readText());
				}
			} else if (tag.equals(STAR_TAG)) {
				//
				if (user != null) {
					user.setStarState(ALNumericUtils.parseInt(readText(), 0));
				}
			} else if (tag.equals(AVATAR_TAG)) {
				if (user != null) {
					// 头像
					user.setImageFileId(getAttValue(AVATAR_TAG));
				}
			} else if (tag.equals(DELETE_TAG)) {
				// 被取消收藏或者被删除粉丝
				deleteType = ALNumericUtils.parseInt(getAttValue("type"), -1);
				if (deleteType == 0) {
					msg.setType(ALMessage.FANS_DELETED_MSG);
				} else if (deleteType == 1) {
					msg.setType(ALMessage.FAVORITE_DELETED_MSG);
				}
			} else if (tag.equals(COUNT_TAG)) {
				if (user != null) {
					user.setFansFriendsCount(ALNumericUtils.parseInt(
							readText(), 0));
				}
			} else if (tag.equals(IN_BLACK_LIST_TAG)) {
				if (user != null) {
					// 黑名单
					user.setInblacklist(ALNumericUtils.parseInt(readText(), 0) == 1 ? true
							: false);
				}
			} else if (tag.equals("price")) {
				if (user != null) {
					user.setCallPrice(readText());
					ALLog.d("呼叫价格" + user.getCallPrice());
				}
			} else if (tag.equals("delay")) {
				// 获取离线时间
				String stamp = getAttValue("stamp");
				if (!TextUtils.isEmpty(stamp)) {
					msg.setIsOffilneMessage(true);
				}
				if (stamp.length() > 0) {
					msg.setDate(getTimeFromUTC(stamp));
					msg.setTime(getTimeFromUTC(stamp));
				}
			} else if (tag.equals("time")) {
				// 留言时间
				String time = readText();
				if (!type.equals("favorite")) {
					if (time != null && time.length() > 0
							&& time.matches("\\d*")) {
						msg.setTime(new Date(Long.parseLong(time) * 1000));
						msg.setDate(new Date(Long.parseLong(time) * 1000));
					}
				}
			} else if (tag.equals("subject")) {
				if (TextUtils.isEmpty(msg.getSubject())) {
					msg.setSubject(readText());
				}
			} else if (tag.equals("subject2")) {
				msg.setSubject(readText());
			} else if (tag.equals("button")) {
				ButtonInfo info = new ButtonInfo();
				info.setUrl(getAttValue("href"));
				info.setName(readText());
				buttonList.add(info);
			} else if (tag.equals(FROM_AVATAR)) {
				msg.setFromAvatar(readText());
			}
			/************************* voip ***************************/
			else if (tag.equals("sessionid")) {
				msg.setVoipSession(mParser.readText());
			} else if (tag.equals(NAT_TAG)) {
				ip = getAttValue(IP_TAG);
				port = ALNumericUtils.parseInt(getAttValue(PORT_TAG), 4000);
				msg.setNatIp(ip);
				msg.setNatPort(port);
				ALLog.d(NAT_TAG + " ip " + ip + " port " + port);
			} else if (tag.equals(LAN_TAG)) {
				ip = getAttValue(IP_TAG);
				port = ALNumericUtils.parseInt(getAttValue(PORT_TAG), 4000);
				msg.setLanIp(ip);
				msg.setLanPort(port);
				ALLog.d(LAN_TAG + " ip " + ip + " port " + port);

			} else if (tag.equals(TRANSFER_TAG)) {
				ip = getAttValue(IP_TAG);
				port = ALNumericUtils.parseInt(getAttValue(PORT_TAG), 4000);
				msg.setTransferIp(ip);
				msg.setTransferPort(port);
				ALLog.d("ip " + ip + " port " + port);
			} else if (tag.equals("miss")) {
				int missState = ALNumericUtils.parseInt(readText(), 0);
				if (missState == 1) {
					// 是否为来电提醒
					user.setCallRecordType(User.CALL_STATE_MISS);
				}
			} else if (tag.equals("photos")) {
				photos = new ArrayList<ALPhoto>();
			} else if (tag.equals("photo")) {
				ALPhoto p = new ALPhoto();
				p.setOrder(getAttValue("id"));
				p.setThumbnailFileid(getAttValue("small_pic"));
				p.setPicFileid(getAttValue("large_pic"));
				photos.add(p);
			} else if (tag.equals(IS_FRIEND_TAG)) {
				// 好友关系
				String tmp = readText();
				if (user != null) {
					user.setIsfriend(tmp);
				}
			} else if (tag.equals("url")) {
				// 语音url
				String tmp = readText();
				msg.setAudioFaceId(tmp);
			}

			/************************* voip ***************************/
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Override
	public void onTagEnd(String tag) {
		// TODO Auto-generated method stub
		if (tag.equals("photos")) {
			if (user != null) {
				user.setPhotos(photos);
			}
		}
	}

	@Override
	public void onDocumentStart() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onDocumentEnd() {
		// TODO Auto-generated method stub
		// 解析完成，回调通知
		onCallback();
	}

	private void onCallback() {
		if (!TextUtils.isEmpty(type) && !type.equals("error")) {
			if (mListener != null) {
				msg.setData(user);
				msg.setButtonList(buttonList);
				mListener.onReceiveMessage(msg);
			}
		} else {
			if (mListener != null) {
				// 回执来的，不需要发回执,直接通知
				mListener.onReceiveMessageBackEvent(msg.getFrom(),
						msg.getMsgId());
			}
		}
	}

	private void checkALMessageType() {
		if (TextUtils.isEmpty(type)) {
			return;
		}

		if ("voipcall".equals(type)) {
			ALLog.d(" incoming call... ");
			msg.setType(ALMessage.NEW_INCOMMING_CALL);
			user = new User();
		} else if ("voipresponse".equals(type)) {
			ALLog.d("user accept call");
			msg.setType(ALMessage.USER_ACCEPT_CALL);
		} else if ("voipreject".equals(type)) {
			ALLog.d("user reject call");
			msg.setType(ALMessage.USER_REJECT_CALL);
		} else if ("voipend".equals(type)) {
			ALLog.d("user hand up call");
			msg.setType(ALMessage.USER_HANDUP_CALL);
		} else if ("voipaddr".equals(type)) {
			ALLog.d("user addr set");
			msg.setType(ALMessage.USER_VOIP_ADDR_SET);
		} else if (type.equals("favorite")) {
			user = new User();
			// 首先設為收藏消息
			msg.setType(ALMessage.FAVORITE_MSG);
			ALLog.d("收到收藏消息");
		} else if (type.equals("system")) {
			// 系统消息
			ALLog.d("系统消息");
			msg.setType(ALMessage.SYSTEM);
		} else if (type.equals("tmp-image")) {
			msg.setType(ALMessage.CALL_IMAGE_MSG);
		} else if (type.equals("audioleave")) {
			msg.setType(ALMessage.AUDIO_LEAVE);
		}
	}

	private String getAttValue(String key) {
		return mParser.getAttValue(key);
	}

	private String readText() throws XmlPullParserException, IOException {
		return mParser.readText();
	}

	private Date getTimeFromUTC(String ts) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(
					"yyyy-MM-dd'T'HH:mm:ss'Z'");
			sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
			Date dt = sdf.parse(ts);
			return dt;
		} catch (ParseException pe) {
			pe.printStackTrace();
		}
		return null;
	}

}
